// *************************************************************************************************
//
// MK3D Engine
// --------------------------------------
// Copyright (C) 2007-2011 Zeb (mailto: zebbey@gmail.com)
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// *************************************************************************************************

#ifndef __H_MK_REPR_TERRAIN__
#define __H_MK_REPR_TERRAIN__

#include "mk_entity.h"

namespace MK3DE
{
	class CScene;
	class CEntityTerrainRegion;
	class CTerrainHeightBrush;
	class CTerrainLayerBrush;
	class CMaterial;

	class MK3DE_API CEntityTerrain : public CEntity
	{
	public:
		CEntityTerrain(CScene* pScene);
		~CEntityTerrain();

		//! Get entity render type and entity type.
		ENTITY_RENDER_TYPE GetRenderType() { return ERT_SOLID; }
		ENTITY_TYPE GetType() { return ET_TERRAIN; }

		//! Load terrain from terrain file.
		BOOL LoadFromFile(const char* fileName);

		//! Get terrain file name if it's loaded from file.
		std::string GetFileName() { return _fileName; }

		//! Create all terrain region object. Should create all regions one by one.
		BOOL Create(int regionWidth, int regionHeight);

		//! Link all region with their neighbor.
		void LinkAllRegion();

		//! Get region width.
		DWORD GetRegionWidth() { return _width; }

		//! Get region height.
		DWORD GetRegionHeight() { return _height; }

		//! Get terrain region by region index.
		BOOL GetTerrainRegionByIndex(int regionX, int regionY, /* out */ CEntityTerrainRegion*& region);

		//! Get terrain region by coordinate.
		BOOL GetTerrainRegionByPos(float x, float y, /* out */ CEntityTerrainRegion*& region);

		//! Get terrain ground height.
		BOOL GetGroundHeight(/* out */ float& height, float x, float y);

		//! Pick terrain ground from screen coordinate.
		BOOL Pick(/* out */ D3DXVECTOR3& intersect, D3DXVECTOR2& pos2D);

		//! Use a height brush to paint terrain height.
		BOOL PaintHeight(CTerrainHeightBrush* brush);

		//! Use a terrain layer brush to paint terrain layer blend weight.
		BOOL PaintLayer(CTerrainLayerBrush* brush, const char* fileName);

		//! Recalculate all region's noraml.
		void RecalculateNormal();

		//! Update all region's position vertex buffer.
		BOOL UpdatePositionVertexBuffer();

		//! Update all region's normal vertex buffer.
		BOOL UpdateNormalVertexBuffer();

		//! Update all region's texture coordinate vertex buffer.
		BOOL UpdateTextureCoordVertexBuffer();

		//! Get terrain material.
		CMaterial* GetMaterial() { return _material; }

		////! Use ray trace to calculate static light-map.
		//BOOL GenerateLightMapRayTrace(const char* mapName, DWORD regionX, DWORD regionY, DWORD mapWidth, DWORD mapHeight, D3DXVECTOR3& lightDir);

		////! Use shadow-mapping to calculate static light-map.
		//BOOL GenerateLightMapShadowMapping(const char* mapName, DWORD regionX, DWORD regionY, DWORD mapSize, D3DXVECTOR3& lightDir, float blurSize, float shadowFactor);

	public:
		void _AttachSceneNode(CSceneNode* pNode);
		void ViewFrustumCulling(CCamera* camera, std::vector<CEntity*>& vecEntity);

	private:
		void __Clean();
		BOOL __GetIntersection(D3DXVECTOR3& intersect, D3DXVECTOR3& v1, D3DXVECTOR3& v2);
		//BOOL __CollideWithRay(D3DXVECTOR3& pos, float x, float y, float z, D3DXVECTOR3& dir);
		//void __GenerateShadowCasterList(CSceneNode* node, std::vector<CSceneNode*>& list);
		//BOOL __SceneShadowCasterCollideWithRay(D3DXVECTOR3& pos, float x, float y, float z, D3DXVECTOR3& lightDir, std::vector<CSceneNode*> vecShadowCaster);
		//BOOL __ConstructLightViewProjMatrix(D3DXMATRIX& viewMatrix, D3DXMATRIX& projMatrix, CEntityTerrainRegion* region, D3DXVECTOR3& lightDir);
		//void __GaussianBlurH(BYTE* buffer, DWORD pitch, DWORD mapSize, float blurSize);
		//void __GaussianBlurV(BYTE* buffer, DWORD pitch, DWORD mapSize, float blurSize);

	private:
		DWORD _width;
		DWORD _height;

		std::string _fileName;

		std::vector<CEntityTerrainRegion*> _vecTerrainRegion;

		CMaterial* _material;
	};
};

#endif // __H_MK_REPR_TERRAIN__